import * as turf from '@turf/turf'

class MapCore {
  constructor(map) {
    this.currentPoints = []
    this.currentPolygons = []
    let str = ''
    // 避免重复创建新的实例
    if (map === undefined && MapCore.instance) {
      // str = '-------------------- 地图已初始化 --------------------'
      // console.log(str)
      return MapCore.instance
    } else {
      str = '-------------------- 地图初始化中 --------------------'
      console.log(str)
    }
    this.map = map
    this.polygonsLayer = this.map.layer()
    this.pointsLayer = this.map.layer() // 打点专有图层
    this.imageLayer = this.map.layer()
    MapCore.instance = this
  }

  addPolygons (coordinates, options) {
    const polygons = this.polygonsLayer.addPolygons(coordinates, options)
    this.currentPolygons = this.currentPolygons.concat(polygons)
    return polygons
  }

  addPolylines (coordinates, options) {
    const polygons = this.polygonsLayer.addPolylines(coordinates, options)
    this.currentPolygons = this.currentPolygons.concat(polygons)
    return polygons
  }

  addImage (coordinates, url) {
    const imageLayer = this.imageLayer.addImage(
      { coordinates: coordinates },
      { url: url }
    )
    return imageLayer
  }

  addPoints (coordinates, params = { showTooltip: true }) {
    const points = this.pointsLayer.addPoints(coordinates, (data) => {
      let featureOptions = {
        draggable: false,
        // offset:[10,10],
        // angle:30,
        tag: data.tag,
        src: data.src || 'circle',
        icon: data.icon,
        label: data.label,
        size: data.size || [48, 56],
        fillColor: data.fillColor || '#fff',
        opacity: data.opacity || 1,
        zIndex: data.opacity || 999,
        fillOpacity: data.fillOpacity || 1,
        // collisionFlag: true //是否开启碰撞隐藏
      }
      if (data.zIndex) featureOptions.zIndex = data.zIndex
      return {
        feature: featureOptions,
        tooltip: !params.showTooltip ? null : {
          zoom: 13,
          text: data.name,
          direction: 'top',
          offset: [0, -15],
          className: 'points-tooltip'
        },
      };
    })
    this.currentPoints = this.currentPoints.concat(points)
    return points
  }

  /**
   * 单水库打点
   */
  addReservoirPoints (coordinates) {
    const points = this.pointsLayer.addPoints(coordinates, (data) => {
      let featureOptions = {
        draggable: false,
        tag: data.tag,
        src: data.src || 'circle',
        icon: data.icon,
        label: data.label,
        size: data.size || [48, 56],
        fillColor: data.fillColor || '#fff',
        opacity: data.opacity || 1,
        fillOpacity: data.fillOpacity || 1,
      }
      if (data.zIndex) featureOptions.zIndex = data.zIndex
      return {
        feature: featureOptions,
        tooltip: {
          interactive: true,
          zoom: 16,
          text: data.name,
          direction: 'top',
          offset: [0, -15],
          className: 'points-tooltip'
        }
      }
    })
    this.currentPoints = this.currentPoints.concat(points)
    return points
  }

  setView (position, zoom) {
    this.map.setView(position, zoom)
  }

  setCenterZoom (position, zoom) {
    this.map.setCenterZoom(position, zoom)
  }

  flyTo (position, zoom) {
    this.map.flyTo(position, zoom)
  }
  /**
   * 根据测站ID删除点位
   * @param stcd
   */
  removePoint (stcd) {
    this.currentPoints.forEach(item => {
      if(item.__data.stcd === stcd || item.__data.id === stcd) {
        item.remove()
      }
    })
    this.currentPoints = this.currentPoints.filter(item => item.__data.stcd !== stcd)
  }

  /**
   * 删除所有点位
   */
  removeAllPoints () {
    this.currentPoints.forEach(item => {
      item.remove()
    })
    this.currentPoints = []
  }

  /**
   * 根据面名称删除polygons
   * @param pName
   */
  removePolygons (pName) {
    this.currentPolygons.forEach(item => {
      if(item.__data.pName === pName) {
        item.remove()
      }
    })
    this.currentPolygons = this.currentPolygons.filter(item => item.__data.pName !== pName)
  }

  clearLayer (type = 'point') {
    if (type === 'point') this.pointsLayer.clear()
    if (type === 'polygon') this.polygonsLayer.clear()
  }

   // 洪水预演(L)
   showFloodLayer (geojson, isFly, offset) {
    this.removeLayer(this.map.map, 'floodGeojson')
    let style = (feature) => {
      let colors = [ '#88BA3D', '#00C782', '#3180FF', '#FFC400', '#FF8900', '#FF4545' ]
      let vals = [ 0.5, 1, 1.5, 2.5, 5 ]
      let val = feature.properties.Depth
      let color = '#88BA3D'
      if (val < vals[0]) {
        color = colors[0]
      } else if (val >= vals[0] && val < vals[1]) {
        color = colors[1]
      } else if (val >= vals[1] && val < vals[2]) {
        color = colors[2]
      } else if (val >= vals[2] && val < vals[3]) {
        color = colors[3]
      } else if (val >= vals[3] && val < vals[4]) {
        color = colors[4]
      } else if (val >= vals[4]) {
        color = colors[5]
      }
      return {
        color,
        weight: 0,
        fillOpacity: 0.8
      }
    }
    // 第一次定位到中心（带偏移）
    if (isFly) {
      let center = turf.centroid(geojson)?.geometry?.coordinates
      if (offset) center[0] = center[0] - 0.0001
      this.map.map.flyTo([center[1], center[0]], 14, {
        animate: false
      })
    }
    this.addGeojsonToMap(this.map.map, geojson, {id: 'floodGeojson', isFly: false, style })
  }

  // 通过id获取图层(L)
  getLayerById = (map, id) => {
    var L = window.L
    let layer = null
    map.eachLayer(function (event) {
      // check if the layer is a LayerGroup and if its ID matches the one you want
      if (event instanceof L.LayerGroup && event.options.id === id) {
        layer = event
      }
    })
    return layer
  }

  // 通过id，删除图层(L)
  removeLayer = (map, id) => {
    let pointLayer = this.getLayerById(map, id)
    if (pointLayer) map.removeLayer(pointLayer)
  }

  // 添加geojson (L)
  addGeojsonToMap (map, geojson, option = {}) {
    var L = window.L
    const isValid = this.isGeoJSONValid(geojson)
    if (!isValid) return
    var defaultStyle = () => {
      return {
        color: '#fff',
        weight: 2,
        fillColor: '#fff',
        fillOpacity: 1
      }
    }
    if (!map || !geojson) return
    const { style = defaultStyle, isFly = false, id = Math.random().toString(16).slice(2), click, init } = option
    if (!geojson) {
      return
    }
    let geojsonLayerContrl = this.getLayerById(map, id)
    if (!geojsonLayerContrl) {
      geojsonLayerContrl = L.layerGroup([], { id }).addTo(map)
    } else {
      console.error('已存在该图层', id)
    }
    var geojsonLayer = L.geoJSON(geojson, {
      style,
      onEachFeature: function (feature, layer) {
        if (typeof click === 'function') {
          layer.on('click', click)
        }
        if (typeof init === 'function') {
          init(feature, layer)
        }
      }
    })
    geojsonLayer.addTo(geojsonLayerContrl)
    if (isFly) {
      // 计算 geojson 边界和地图容器大小，动态计算缩放级别
      const bounds = geojsonLayer.getBounds()
      const topLeft = L.latLng(bounds.getNorth(), bounds.getWest())
      const bottomRight = L.latLng(bounds.getSouth(), bounds.getEast())
      const mapSize = L.point(map.getSize().x, map.getSize().y)
      const maxBoundsSize = Math.max(bounds.getEast() - bounds.getWest(), bounds.getSouth() - bounds.getNorth())
      const zoom = map.getBoundsZoom(L.latLngBounds(topLeft, bottomRight), false, mapSize.divideBy(2)) - Math.log(maxBoundsSize / (Math.min(mapSize.x, mapSize.y) * 0.5)) / Math.log(2)

      // 移动地图视角到 geojson 中心位置
      map.setView(bounds.getCenter(), zoom)
    }
    return geojsonLayer
  }

  // 判断是否是geojson数据
  isGeoJSONValid = (geojson) => {
    if (!geojson) {
      return false
    }
    try {
      const geojsonObj = typeof geojson === 'object' ? geojson : JSON.parse(geojson)
      if (!geojsonObj || !geojsonObj.type) {
        return false
      }
      if (['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon', 'GeometryCollection', 'Feature', 'FeatureCollection'].indexOf(geojsonObj.type) === -1) {
        return false
      }
    } catch (e) {
      return false
    }
    return true
  }


  /**
   * 销毁实例
   */
  destroy () {
    if (this.polygonsLayer) {
      this.polygonsLayer.clear()
      this.polygonsLayer = null
    }
    if (this.pointsLayer) {
      this.pointsLayer.clear()
      this.pointsLayer = null
    }
    this.map = null
    const str = '-------------------- 地图销毁中 --------------------'
    console.log(str)
  }
}

export default MapCore
